<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>part2_4_parameters - learning-gem5</title>
        <!-- Custom HTML head -->
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        <link rel="icon" href="../favicon.svg">
        <link rel="shortcut icon" href="../favicon.png">
        <link rel="stylesheet" href="../css/variables.css">
        <link rel="stylesheet" href="../css/general.css">
        <link rel="stylesheet" href="../css/chrome.css">
        <link rel="stylesheet" href="../css/print.css" media="print">
        <!-- Fonts -->
        <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../fonts/fonts.css">
        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../highlight.css">
        <link rel="stylesheet" href="../tomorrow-night.css">
        <link rel="stylesheet" href="../ayu-highlight.css">

        <!-- Custom theme stylesheets -->
    </head>
    <body>
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded affix "><a href="../part0_introduction.html">Learning gem-5</a></li><li class="chapter-item expanded "><a href="../part0_introduction.html"><strong aria-hidden="true">1.</strong> part0_introduction</a></li><li class="chapter-item expanded "><a href="../part1/part1_1_building.html"><strong aria-hidden="true">2.</strong> part1</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../part1/part1_1_building.html"><strong aria-hidden="true">2.1.</strong> part1_1_building</a></li><li class="chapter-item expanded "><a href="../part1/part1_2_simple_config.html"><strong aria-hidden="true">2.2.</strong> part1_2_simple_config</a></li><li class="chapter-item expanded "><a href="../part1/part1_3_cache_config.html"><strong aria-hidden="true">2.3.</strong> part1_3_cache_config</a></li><li class="chapter-item expanded "><a href="../part1/part1_4_gem5_stats.html"><strong aria-hidden="true">2.4.</strong> part1_4_gem5_stats</a></li><li class="chapter-item expanded "><a href="../part1/part1_5_gem5_example_configs.html"><strong aria-hidden="true">2.5.</strong> part1_5_gem5_example_configs</a></li><li class="chapter-item expanded "><a href="../part1/part1_6_extending_configs.html"><strong aria-hidden="true">2.6.</strong> part1_6_extending_configs</a></li></ol></li><li class="chapter-item expanded "><a href="../part2/part2_0_environment.html"><strong aria-hidden="true">3.</strong> part2</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../part2/part2_0_environment.html"><strong aria-hidden="true">3.1.</strong> part2_0_environment</a></li><li class="chapter-item expanded "><a href="../part2/part2_1_helloobject.html"><strong aria-hidden="true">3.2.</strong> part2_1_helloobject</a></li><li class="chapter-item expanded "><a href="../part2/part2_2_debugging.html"><strong aria-hidden="true">3.3.</strong> part2_2_debugging</a></li><li class="chapter-item expanded "><a href="../part2/part2_3_events.html"><strong aria-hidden="true">3.4.</strong> part2_3_events</a></li><li class="chapter-item expanded "><a href="../part2/part2_4_parameters.html" class="active"><strong aria-hidden="true">3.5.</strong> part2_4_parameters</a></li><li class="chapter-item expanded "><a href="../part2/part2_5_memoryobject.html"><strong aria-hidden="true">3.6.</strong> part2_5_memoryobject</a></li><li class="chapter-item expanded "><a href="../part2/part2_6_simplecache.html"><strong aria-hidden="true">3.7.</strong> part2_6_simplecache</a></li><li class="chapter-item expanded "><a href="../part2/part2_7_arm_power_modelling.html"><strong aria-hidden="true">3.8.</strong> part2_7_arm_power_modelling</a></li><li class="chapter-item expanded "><a href="../part2/part2_8_arm_dvfs_support.html"><strong aria-hidden="true">3.9.</strong> part2_8_arm_dvfs_support</a></li></ol></li><li class="chapter-item expanded "><a href="../part3/part3_00_MSIntro.html"><strong aria-hidden="true">4.</strong> part3</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../part3/part3_00_MSIntro.html"><strong aria-hidden="true">4.1.</strong> part3_00_MSIntro</a></li><li class="chapter-item expanded "><a href="../part3/part3_01_cache-intro.html"><strong aria-hidden="true">4.2.</strong> part3_01_cache-intro</a></li><li class="chapter-item expanded "><a href="../part3/part3_02_cache-declarations.html"><strong aria-hidden="true">4.3.</strong> part3_02_cache-declarations</a></li><li class="chapter-item expanded "><a href="../part3/part3_03_cache-in-ports.html"><strong aria-hidden="true">4.4.</strong> part3_03_cache-in-ports</a></li><li class="chapter-item expanded "><a href="../part3/part3_04_cache_actions.html"><strong aria-hidden="true">4.5.</strong> part3_04_cache_actions</a></li><li class="chapter-item expanded "><a href="../part3/part3_05_cache_transitions.html"><strong aria-hidden="true">4.6.</strong> part3_05_cache_transitions</a></li><li class="chapter-item expanded "><a href="../part3/part3_06_directory.html"><strong aria-hidden="true">4.7.</strong> part3_06_directory</a></li><li class="chapter-item expanded "><a href="../part3/part3_07_MSIbuilding.html"><strong aria-hidden="true">4.8.</strong> part3_07_MSIbuilding</a></li><li class="chapter-item expanded "><a href="../part3/part3_08_configuration.html"><strong aria-hidden="true">4.9.</strong> part3_08_configuration</a></li><li class="chapter-item expanded "><a href="../part3/part3_09_running.html"><strong aria-hidden="true">4.10.</strong> part3_09_running</a></li><li class="chapter-item expanded "><a href="../part3/part3_10_MSIdebugging.html"><strong aria-hidden="true">4.11.</strong> part3_10_MSIdebugging</a></li><li class="chapter-item expanded "><a href="../part3/part3_11_simple-MI_example.html"><strong aria-hidden="true">4.12.</strong> part3_11_simple-MI_example</a></li></ol></li><li class="chapter-item expanded "><a href="../part4_gem5_101.html"><strong aria-hidden="true">5.</strong> part4_gem5_101</a></li><li class="chapter-item expanded "><a href="../http://doxygen.gem5.org/develop/index.html"><strong aria-hidden="true">6.</strong> part4_gem5_102</a></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky bordered">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">learning-gem5</h1>

                    <div class="right-buttons">
                        <a href="../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>
                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>
                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="向-simobjects-和更多事件添加参数"><a class="header" href="#向-simobjects-和更多事件添加参数">向 SimObjects 和更多事件添加参数</a></h1>
<p>gem5 的 Python 接口最强大的部分之一是能够将参数从 Python 传递到 gem5 中的 C++ 对象。在本章，我们将研究几种SimObject参数以及如何利用它们继续构建<a href="http://www.gem5.org/documentation/learning_gem5/part2/helloobject/">前面章节</a>的<code>HelloObject</code>。</p>
<h2 id="简单参数"><a class="header" href="#简单参数">简单参数</a></h2>
<p>首先，我们在<code>HelloObject</code>中为延迟和触发事件的次数添加参数。要添加参数，请修改SimObject Python 文件 ( <code>src/learning_gem5/part2/HelloObject.py</code>) 中的<code>HelloObject</code>类。通过向包含<code>Param</code>类型的 Python 类添加新语句来设置参数。</p>
<p>例如，下面的代码有一个参数<code>time_to_wait</code>，它是一个“延迟”参数，<code>number_of_fires</code>它是一个整数参数。</p>
<pre><code class="language-python">class HelloObject(SimObject):
    type = 'HelloObject'
    cxx_header = &quot;learning_gem5/part2/hello_object.hh&quot;

    time_to_wait = Param.Latency(&quot;Time before firing the event&quot;)
    number_of_fires = Param.Int(1, &quot;Number of times to fire the event before &quot;
                                   &quot;goodbye&quot;)
</code></pre>
<p><code>Param.&lt;TypeName&gt;</code>声明一个类型为<code>TypeName</code>的参数。常见类型<code>Int</code>是整数、<code>Float</code>是浮点数等。这些类型的行为类似于常规 Python 类。</p>
<p>每个参数声明采用一个或两个参数。当给定两个参数时（如<code>number_of_fires</code>），第一个是参数的 <em>默认值</em>。在这种情况下，如果您在 Python 配置文件中实例化<code>HelloObject</code>而没有为 <code>number_of_fires</code> 指定任何值，它将采用默认值 1。</p>
<p>参数声明的第二个参数是对参数的<code>简短描述</code>。这必须是 Python 字符串。如果您只为参数声明指定一个参数，则它是描述（如<code>time_to_wait</code>）。</p>
<p>gem5 还支持许多复杂的参数类型，而不仅仅是内置类型。例如，<code>time_to_wait</code>是一个<code>Latency</code>。<code>Latency</code> 将一个值作为时间值的字符串并将其转换为模拟器的时钟周期数（<strong>ticks</strong>）。例如，具有1皮秒（每秒 1 THz 或 10^12^ ticks）的缺省tick速率，<code>&quot;1ns&quot;</code>自动转换至1000。还有其他便利的参数，如<code>Percent</code>， <code>Cycles</code>，<code>MemorySize</code>等等。</p>
<p>在 SimObject 文件中声明这些参数后，您需要将它们的值复制到 C++ 类的构造函数中。以下代码显示了对<code>HelloObject</code>构造函数的更改。</p>
<pre><code class="language-cpp">HelloObject::HelloObject(const HelloObjectParams &amp;params) :
    SimObject(params),
    event(*this),
    myName(params.name),
    latency(params.time_to_wait),
    timesLeft(params.number_of_fires)
{
    DPRINTF(Hello, &quot;Created the hello object with the name %s\n&quot;, myName);
}
</code></pre>
<p>在这里，我们使用参数的值作为延迟和时间的默认值。此外，我们存储来自参数对象的<code>name</code> ，以便稍后在成员变量<code>myName</code>中使用它。每个<code>params</code> 实例化都有一个名称，该名称来自实例化时的 Python 配置文件。</p>
<p>但是，此处分配名称只是使用 params 对象的一个示例。对于所有 SimObjects，都有一个<code>name()</code>函数总是返回名称。因此，永远不需要像上面那样存储名称。</p>
<p>在 HelloObject 类声明中，为名称添加一个成员变量。</p>
<pre><code class="language-cpp">class HelloObject : public SimObject
{
  private:
    void processEvent();

    EventWrapper event;

    const std::string myName;//为名称添加的成员变量

    const Tick latency;

    int timesLeft;

  public:
    HelloObject(HelloObjectParams *p);

    void startup();
};
</code></pre>
<p>当我们用上面的代码运行 gem5 时，我们得到以下错误：</p>
<pre><code class="language-bash">gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled Jan  4 2017 14:46:36
gem5 started Jan  4 2017 14:46:52
gem5 executing on chinook, pid 3422
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py

Global frequency set at 1000000000000 ticks per second
fatal: hello.time_to_wait without default or user set value
</code></pre>
<p>这是因为该<code>time_to_wait</code>参数没有默认值。因此，我们需要更新 Python 配置文件 ( <code>run_hello.py</code>) 以指定此值。</p>
<pre><code class="language-python">root.hello = HelloObject(time_to_wait = '2us')
</code></pre>
<p>或者，我们可以指定<code>time_to_wait</code>为成员变量。两种做法是等价的，因为 C++ 对象在<code>m5.instantiate()</code>被调用之前不会被创建 。</p>
<pre><code class="language-python">root.hello = HelloObject()
root.hello.time_to_wait = '2us'
</code></pre>
<p>附加<code>Hello</code>调试标志运行时，这个简单脚本的输出如下 。</p>
<pre><code class="language-bash">gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled Jan  4 2017 14:46:36
gem5 started Jan  4 2017 14:50:08
gem5 executing on chinook, pid 3455
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py

Global frequency set at 1000000000000 ticks per second
      0: hello: Created the hello object with the name hello
Beginning simulation!
info: Entering event queue @ 0.  Starting simulation...
2000000: hello: Hello world! Processing the event! 0 left
2000000: hello: Done firing!
Exiting @ tick 18446744073709551615 because simulate() limit reached
</code></pre>
<p>您还可以修改配置脚本以多次触发事件。</p>
<h2 id="其他-simobjects-作为参数"><a class="header" href="#其他-simobjects-作为参数">其他 SimObjects 作为参数</a></h2>
<p>您还可以指定其他 SimObject 作为参数。为了证明这一点，我们将创建一个新的SimObject， <code>GoodbyeObject</code>。这个对象将有一个简单的函数，对另一个 SimObject 说“再见”。为了让它更有趣一点，<code>GoodbyeObject</code>将有一个缓冲区来写入消息，并有一个有限的带宽来写入消息。</p>
<p>首先，在 SConscript 文件中声明 SimObject：</p>
<pre><code class="language-python">Import('*')

SimObject('HelloObject.py')
Source('hello_object.cc')
Source('goodbye_object.cc')

DebugFlag('Hello')
</code></pre>
<p>可以在<a href="https://www.gem5.org/_pages/static/scripts/part2/parameters/SConscript">此处</a>下载新的 SConscript 文件 。</p>
<p>接下来，您需要在 SimObject Python 文件中声明新的 SimObject。由于<code>GoodbyeObject</code>与<code>HelloObject</code>高度相关，我们将使用相同的文件。您可以将以下代码添加到 <code>HelloObject.py</code>.</p>
<pre><code class="language-python">class GoodbyeObject(SimObject):
    type = 'GoodbyeObject'
    cxx_header = &quot;learning_gem5/part2/goodbye_object.hh&quot;

    buffer_size = Param.MemorySize('1kB',
                                   &quot;Size of buffer to fill with goodbye&quot;)
    write_bandwidth = Param.MemoryBandwidth('100MB/s', &quot;Bandwidth to fill &quot;
                                            &quot;the buffer&quot;)
</code></pre>
<p>这个对象有两个参数，都有默认值。第一个参数是缓冲区的大小，是一个<code>MemorySize</code>参数。其次是<code>write_bandwidth</code>指定填充缓冲区的速度。一旦缓冲区已满，模拟将退出。</p>
<p>更新后的<code>HelloObject.py</code>文件可以在<a href="https://www.gem5.org/_pages/static/scripts/part2/parameters/HelloObject.py">这里</a>下载 。</p>
<p>现在，我们需要实现<code>GoodbyeObject</code>.</p>
<pre><code class="language-cpp">#ifndef __LEARNING_GEM5_GOODBYE_OBJECT_HH__
#define __LEARNING_GEM5_GOODBYE_OBJECT_HH__

#include &lt;string&gt;

#include &quot;params/GoodbyeObject.hh&quot;
#include &quot;sim/sim_object.hh&quot;

class GoodbyeObject : public SimObject
{
  private:
    void processEvent();

    /**
     * Fills the buffer for one iteration. If the buffer isn't full, this
     * function will enqueue another event to continue filling.
     */
    void fillBuffer();

    EventWrapper&lt;GoodbyeObject, &amp;GoodbyeObject::processEvent&gt; event;

    /// The bytes processed per tick
    float bandwidth;

    /// The size of the buffer we are going to fill
    int bufferSize;

    /// The buffer we are putting our message in
    char *buffer;

    /// The message to put into the buffer.
    std::string message;

    /// The amount of the buffer we've used so far.
    int bufferUsed;

  public:
    GoodbyeObject(GoodbyeObjectParams *p);
    ~GoodbyeObject();

    /**
     * Called by an outside object. Starts off the events to fill the buffer
     * with a goodbye message.
     *
     * @param name the name of the object we are saying goodbye to.
     */
    void sayGoodbye(std::string name);
};

#endif // __LEARNING_GEM5_GOODBYE_OBJECT_HH__
</code></pre>
<pre><code class="language-cpp">#include &quot;learning_gem5/part2/goodbye_object.hh&quot;

#include &quot;debug/Hello.hh&quot;
#include &quot;sim/sim_exit.hh&quot;

GoodbyeObject::GoodbyeObject(const GoodbyeObjectParams &amp;params) :
    SimObject(params), event(*this), bandwidth(params.write_bandwidth),
    bufferSize(params.buffer_size), buffer(nullptr), bufferUsed(0)
{
    buffer = new char[bufferSize];
    DPRINTF(Hello, &quot;Created the goodbye object\n&quot;);
}

GoodbyeObject::~GoodbyeObject()
{
    delete[] buffer;
}

void
GoodbyeObject::processEvent()
{
    DPRINTF(Hello, &quot;Processing the event!\n&quot;);
    fillBuffer();
}

void
GoodbyeObject::sayGoodbye(std::string other_name)
{
    DPRINTF(Hello, &quot;Saying goodbye to %s\n&quot;, other_name);

    message = &quot;Goodbye &quot; + other_name + &quot;!! &quot;;

    fillBuffer();
}

void
GoodbyeObject::fillBuffer()
{
    // There better be a message
    assert(message.length() &gt; 0);

    // Copy from the message to the buffer per byte.
    int bytes_copied = 0;
    for (auto it = message.begin();
         it &lt; message.end() &amp;&amp; bufferUsed &lt; bufferSize - 1;
         it++, bufferUsed++, bytes_copied++) {
        // Copy the character into the buffer
        buffer[bufferUsed] = *it;
    }

    if (bufferUsed &lt; bufferSize - 1) {
        // Wait for the next copy for as long as it would have taken
        DPRINTF(Hello, &quot;Scheduling another fillBuffer in %d ticks\n&quot;,
                bandwidth * bytes_copied);
        schedule(event, curTick() + bandwidth * bytes_copied);
    } else {
        DPRINTF(Hello, &quot;Goodbye done copying!\n&quot;);
        // Be sure to take into account the time for the last bytes
        exitSimLoop(buffer, 0, curTick() + bandwidth * bytes_copied);
    }
}

GoodbyeObject*
GoodbyeObjectParams::create()
{
    return new GoodbyeObject(this);
}
</code></pre>
<p>头文件可以在<a href="https://www.gem5.org/_pages/static/scripts/part2/parameters/goodbye_object.hh">这里</a>下载 ，实现可以在<a href="https://www.gem5.org/_pages/static/scripts/part2/parameters/goodbye_object.cc">这里</a>下载 。</p>
<p><code>GoodbyeObject</code>的接口是一个简单的<code>sayGoodbye</code>函数 ，它将一个字符串作为参数。调用此函数时，模拟器会构建消息并将其保存在成员变量中。然后，我们开始填充缓冲区。</p>
<p>为了对有限的带宽进行建模，每次我们将消息写入缓冲区时，我们都会暂停写入消息所需的延迟。我们使用一个简单的事件来模拟这个暂停。</p>
<p>由于我们在 SimObject 声明中使用了一个<code>MemoryBandwidth</code>参数，<code>bandwidth</code>变量会自动转换为每字节读写的tick数，因此计算延迟只是带宽乘以我们想要写入缓冲区的字节数。</p>
<p>最后，当缓冲区已满时，我们调用函数<code>exitSimLoop</code>，它将退出模拟。这个函数有三个参数，第一个是返回Python配置脚本的消息（<code>exit_event.getCause()</code>），第二个是退出代码，第三个是什么时候退出。</p>
<h3 id="将-goodbyeobject-作为参数添加到-helloobject"><a class="header" href="#将-goodbyeobject-作为参数添加到-helloobject">将 GoodbyeObject 作为参数添加到 HelloObject</a></h3>
<p>首先，我们将<code>GoodbyeObject</code>作为参数添加到 <code>HelloObject</code>. 要做到这一点，你只需指定SimObject类名作为<code>TypeName</code>的<code>Param</code>。您可以有一个默认值，也可以没有，就像普通参数一样。</p>
<pre><code class="language-python">class HelloObject(SimObject):
    type = 'HelloObject'
    cxx_header = &quot;learning_gem5/part2/hello_object.hh&quot;

    time_to_wait = Param.Latency(&quot;Time before firing the event&quot;)
    number_of_fires = Param.Int(1, &quot;Number of times to fire the event before &quot;
                                   &quot;goodbye&quot;)

    goodbye_object = Param.GoodbyeObject(&quot;A goodbye object&quot;) # 添加GoodbyeObject
</code></pre>
<p>更新后的<code>HelloObject.py</code>文件可以在<a href="https://www.gem5.org/_pages/static/scripts/part2/parameters/HelloObject.py">这里</a>下载 。</p>
<p>其次，我们会添加<code>GoodbyeObject</code>的引用到 <code>HelloObject</code>类。不要忘记在 <code>hello_object.hh</code> 文件的顶部包含 <code>goodbye_object.hh</code>！</p>
<pre><code class="language-cpp">#include &lt;string&gt;

#include &quot;learning_gem5/part2/goodbye_object.hh&quot;
#include &quot;params/HelloObject.hh&quot;
#include &quot;sim/sim_object.hh&quot;

class HelloObject : public SimObject
{
  private:
    void processEvent();

    EventWrapper event;

    /// Pointer to the corresponding GoodbyeObject. Set via Python
    GoodbyeObject* goodbye;

    /// The name of this object in the Python config file
    const std::string myName;

    /// Latency between calling the event (in ticks)
    const Tick latency;

    /// Number of times left to fire the event before goodbye
    int timesLeft;

  public:
    HelloObject(HelloObjectParams *p);

    void startup();
};
</code></pre>
<p>然后，我们需要更新<code>HelloObject</code>的构造函数和事件处理函数。 我们还在构造函数中添加了检查以确保<code>goodbye</code>指针有效。当<code>goodbye</code>指针为空时我们应该<em>抛出panic()</em>，因为这个对象不是被编码和接受的。</p>
<pre><code class="language-cpp">#include &quot;learning_gem5/part2/hello_object.hh&quot;

#include &quot;base/misc.hh&quot;
#include &quot;debug/Hello.hh&quot;

HelloObject::HelloObject(HelloObjectParams &amp;params) :
    SimObject(params),
    event(*this),
    goodbye(params.goodbye_object),
    myName(params.name),
    latency(params.time_to_wait),
    timesLeft(params.number_of_fires)
{
    DPRINTF(Hello, &quot;Created the hello object with the name %s\n&quot;, myName);
    panic_if(!goodbye, &quot;HelloObject must have a non-null GoodbyeObject&quot;);
}
</code></pre>
<p>一旦我们处理事件的次数达到参数指定值，我们应该调用<code>GoodbyeObject</code>的<code>sayGoodbye</code>函数。</p>
<pre><code class="language-cpp">void
HelloObject::processEvent()
{
    timesLeft--;
    DPRINTF(Hello, &quot;Hello world! Processing the event! %d left\n&quot;, timesLeft);

    if (timesLeft &lt;= 0) {
        DPRINTF(Hello, &quot;Done firing!\n&quot;);
        goodbye.sayGoodbye(myName);
    } else {
        schedule(event, curTick() + latency);
    }
}
</code></pre>
<p>你可以找到更新的头文件 <a href="https://www.gem5.org/_pages/static/scripts/part2/parameters/hello_object.hh">在这里</a>和实现文件 <a href="https://www.gem5.org/_pages/static/scripts/part2/parameters/hello_object.cc">在这里</a>。</p>
<h3 id="更新配置脚本"><a class="header" href="#更新配置脚本">更新配置脚本</a></h3>
<p>最后，我们需要将<code>GoodbyeObject</code>加入到配置脚本中。创建一个新的配置脚本<code>hello_goodbye.py</code>并实例化 hello 和 goodbye 对象。例如，一种可能的脚本如下：</p>
<pre><code class="language-python">import m5
from m5.objects import *

root = Root(full_system = False)

root.hello = HelloObject(time_to_wait = '2us', number_of_fires = 5)
root.hello.goodbye_object = GoodbyeObject(buffer_size='100B')

m5.instantiate()

print(&quot;Beginning simulation!&quot;)
exit_event = m5.simulate()
print('Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause()))
</code></pre>
<p>您可以<a href="https://www.gem5.org/_pages/static/scripts/part2/parameters/hello_goodbye.py">在此处</a>下载此脚本 。</p>
<p>运行此脚本会生成以下输出。</p>
<pre><code class="language-bash">gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled Jan  4 2017 15:17:14
gem5 started Jan  4 2017 15:18:41
gem5 executing on chinook, pid 3838
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/hello_goodbye.py

Global frequency set at 1000000000000 ticks per second
      0: hello.goodbye_object: Created the goodbye object
      0: hello: Created the hello object
Beginning simulation!
info: Entering event queue @ 0.  Starting simulation...
2000000: hello: Hello world! Processing the event! 4 left
4000000: hello: Hello world! Processing the event! 3 left
6000000: hello: Hello world! Processing the event! 2 left
8000000: hello: Hello world! Processing the event! 1 left
10000000: hello: Hello world! Processing the event! 0 left
10000000: hello: Done firing!
10000000: hello.goodbye_object: Saying goodbye to hello
10000000: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10152592: hello.goodbye_object: Processing the event!
10152592: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10305184: hello.goodbye_object: Processing the event!
10305184: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10457776: hello.goodbye_object: Processing the event!
10457776: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10610368: hello.goodbye_object: Processing the event!
10610368: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10762960: hello.goodbye_object: Processing the event!
10762960: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks
10915552: hello.goodbye_object: Processing the event!
10915552: hello.goodbye_object: Goodbye done copying!
Exiting @ tick 10944163 because Goodbye hello!! Goodbye hello!! Goodbye hello!! Goodbye hello!! Goodbye hello!! Goodbye hello!! Goo
</code></pre>
<p>你可以修改这两个<strong>SimObject</strong>的参数，看看整体执行时间（Exiting <strong>@tick 10944163</strong>）是如何变化的。要运行这些测试，您可能需要删除调试标志，以便减少终端的输出。</p>
<p>在接下来的章节中，我们将创建一个更复杂、更有用的 SimObject，最终实现一个简单的阻塞单处理器缓存实现。</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../part2/part2_3_events.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>
                            <a rel="next" href="../part2/part2_5_memoryobject.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>
                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../part2/part2_3_events.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                    <a rel="next" href="../part2/part2_5_memoryobject.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>

        <script type="text/javascript">
            window.playground_copyable = true;
        </script>
        <script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
        <script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="../book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->
    </body>
</html>
